package cn.itcast.account.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.itcast.account.entity.AccountFreeze;
import cn.itcast.account.mapper.AccountFreezeMapper;
import cn.itcast.account.mapper.AccountMapper;
import cn.itcast.account.service.AccountTCCService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;

/**
 * AccountTCCServiceImpl -
 *
 * @author whoamizq
 * @date 2022/8/23 15:54
 **/
@Slf4j
@Service
public class AccountTCCServiceImpl implements AccountTCCService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    @Override
    public void deduct(String userId, int money) {
        // 全局事务id
        String xid = RootContext.getXID();
        // money - 无符号字段
        // 判读是否已经有freeze记录
        AccountFreeze freeze = accountFreezeMapper.selectById(xid);
        if (freeze != null) {
            // 拒绝业务
            return;
        }
        // 1. 扣减可用余额
        accountMapper.deduct(userId, money);
        // 2. 冻结金额，事务状态
        AccountFreeze accountFreeze = new AccountFreeze();
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        // 事务id
        accountFreeze.setXid(xid);
        accountFreezeMapper.insert(accountFreeze);
    }

    @Override
    public boolean confirm(BusinessActionContext ctx) {
        String xid = ctx.getXid();
        // 删除冻结记录
        return accountFreezeMapper.deleteById(xid) > 0;
    }

    @Override
    public boolean cancel(BusinessActionContext ctx) {
        String xid = ctx.getXid();
        String userId = ctx.getActionContext("userId").toString();
        // 恢复数据
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);
        // 空回滚
        if (accountFreeze == null) {
            accountFreeze = new AccountFreeze();
            accountFreeze.setUserId(userId);
            accountFreeze.setFreezeMoney(0);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            // 事务id
            accountFreeze.setXid(xid);
            accountFreezeMapper.insert(accountFreeze);
            return true;
        }
        // 幂等判断
        if (accountFreeze.getState() == AccountFreeze.State.CANCEL) {
            // 已经回滚过，直接返回
            return true;
        }
        accountMapper.refund(accountFreeze.getUserId(), accountFreeze.getFreezeMoney());
        // 冻结金额清0，状态改为cancel
        accountFreeze.setFreezeMoney(0);
        accountFreeze.setState(AccountFreeze.State.CANCEL);
        return accountFreezeMapper.updateById(accountFreeze) > 0;
    }
}
